﻿using System;
using BoldBrick.Core.Logging;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace BoldBrick.SharePoint.CommonControls.DataObjects.Base
{
	/// <summary>
	/// Metadata class for SPFeature
	/// </summary>
	public class Feature
	{
		private readonly string resourceFileName;
		private readonly string titleResourceKey;
		private static readonly ILogger log = Logger.GetLogger(typeof (Feature));

		#region Properties
		
		/// <summary>
		/// ID of the feature
		/// </summary>
		public Guid FeatureID { get; private set; }
		
		#endregion

		#region Constructor
		
		/// <summary>
		/// Constructor for <see cref="Feature"/> object
		/// </summary>
		/// <param name="id">ID of the feature</param>
		/// <param name="resourceFileName">Gets file name of resource file without ".cz-cs.resx" extension</param>
		/// <param name="titleResourceKey">Resource key for title of the feature</param>
		public Feature(string id, string resourceFileName, string titleResourceKey)
			: this(new Guid(id), resourceFileName, titleResourceKey)
		{
		}

		/// <summary>
		/// Constructor for <see cref="Feature"/> object
		/// </summary>
		/// <param name="id">ID of the feature</param>
		/// <param name="resourceFileName">Gets file name of resource file without ".cz-cs.resx" extension</param>
		/// <param name="titleResourceKey">Resource key for title of the feature</param>
		public Feature(Guid id, string resourceFileName, string titleResourceKey)
		{
			this.resourceFileName = resourceFileName;
			this.titleResourceKey = titleResourceKey;
			this.FeatureID = id;
		}

		#endregion

		#region Methods

		/// <summary>
		/// Gets title of the feature
		/// </summary>
		/// <param name="language">Language identifier</param>
		/// <returns>Returns title of the feature</returns>
		public string GetTitle(uint language)
		{
			string source = string.Format("$Resources:{0}", this.titleResourceKey);
			return SPUtility.GetLocalizedString(source, this.resourceFileName, language);
		}
		
		/// <summary>
		/// Deactivates feature if this feature is activated
		/// </summary>
		/// <param name="web">Web context of the feature</param>
		public void TryDeactivate(SPWeb web)
		{
			if (!this.IsActivated(web))
			{
				log.Write(LogLevel.Info, "'{0}' feature is already deactivated in '{1}' web.", this, web.ServerRelativeUrl);
				return;
			}
			this.Deactivate(web);
		}
		
		/// <summary>
		/// Deactivates feature if this feature is activated
		/// </summary>
		/// <param name="site">Site collection context of the feature</param>
		public void TryDeactivate(SPSite site)
		{
			if (!this.IsActivated(site))
			{
				log.Write(LogLevel.Info, "'{0}' feature is already deactivated in '{1}' site.", this, site.Url);
				return;
			}
			this.Deactivate(site);
		}
		
		/// <summary>
		/// Deactivates feature
		/// </summary>
		/// <param name="web">Web context of the feature</param>
		public void Deactivate(SPWeb web)
		{
			log.Write(LogLevel.Info, "Deactivating '{0}' feature in '{1}' web.", this, web.ServerRelativeUrl);
			SPFeature feature = web.Features[this.FeatureID];
			if ( feature == null )
			{
				log.Write(LogLevel.Info, "'{0}' feature is not found in '{1}' web.", this, web.ServerRelativeUrl);
				return;
			}

			web.AllowUnsafeUpdates = true;
			web.Features.Remove(this.FeatureID);
		}

		/// <summary>
		/// Deactivates feature
		/// </summary>
		/// <param name="site">Site collection context of the feature</param>
		public void Deactivate(SPSite site)
		{
			log.Write(LogLevel.Info, "Deactivating '{0}' feature in '{1}' site.", this, site.Url);
			SPFeature feature = site.Features[this.FeatureID];
			if ( feature == null )
			{
				log.Write(LogLevel.Info, "'{0}' feature is not found in '{1}' site.", this, site.Url);
				return;
			}

			site.AllowUnsafeUpdates = true;
			site.Features.Remove(this.FeatureID);
		}
		
		/// <summary>
		/// Activates feature if this feature is not activated
		/// </summary>
		/// <param name="web">Web context of the feature</param>
		public void TryActivate(SPWeb web)
		{
			if (this.IsActivated(web))
			{
				log.Write(LogLevel.Info, "'{0}' feature is already activated in '{1}' web.", this, web.ServerRelativeUrl);
				return;
			}
			
			this.Activate(web);
		}
		
		/// <summary>
		/// Activates feature if this feature is not activated
		/// </summary>
		/// <param name="site">Site collection context of the feature</param>
		public void TryActivate(SPSite site)
		{
			if (this.IsActivated(site))
			{
				log.Write(LogLevel.Info, "'{0}' feature is already activated in '{1}' site.", this, site.Url);
				return;
			}

			this.Activate(site);
		}
		
		/// <summary>
		/// Activates feature
		/// </summary>
		/// <param name="web">Web context of the feature</param>
		public void Activate(SPWeb web)
		{
			log.Write(LogLevel.Info, "Activating '{0}' feature in '{1}' web.", this, web.ServerRelativeUrl);
			web.AllowUnsafeUpdates = true;
			web.Features.Add(this.FeatureID);
		}

		/// <summary>
		/// Activates feature
		/// </summary>
		/// <param name="site">Site collection context of the feature</param>
		public void Activate(SPSite site)
		{
			log.Write(LogLevel.Info, "Activating '{0}' feature in '{1}' site.", this, site.Url);
			site.AllowUnsafeUpdates = true;
			site.Features.Add(this.FeatureID);
		}
		
		/// <summary>
		/// Gets true is feature is activated
		/// </summary>
		/// <param name="web">Web context of the feature</param>
		/// <returns>Returns true is feature is activated</returns>
		public bool IsActivated(SPWeb web)
		{
			SPFeature feature = web.Features[this.FeatureID];
			return feature != null;
		}

		/// <summary>
		/// Gets true is feature is activated
		/// </summary>
		/// <param name="site">Site collection context of the feature</param>
		/// <returns>Returns true is feature is activated</returns>
		public bool IsActivated(SPSite site)
		{
			SPFeature feature = site.Features[this.FeatureID];
			return feature != null;
		}

		/// <summary>
		/// Activates feature. If feature is activated, it will be deactivated first.
		/// </summary>
		/// <param name="web">Web context of the feature</param>
		public void ReactivateFeature(SPWeb web)
		{
			bool isActivated = this.IsActivated(web);
			if (isActivated)
				this.Deactivate(web);

			this.Activate(web);
		}

		/// <summary>
		/// Activates feature. If feature is activated, it will be deactivated first.
		/// </summary>
		/// <param name="site">Site collection context of the feature</param>
		public void ReactivateFeature(SPSite site)
		{
			bool isActivated = this.IsActivated(site);
			if (isActivated)
				this.Deactivate(site);

			this.Activate(site);
		}

		public override string ToString()
		{
			string title = GetTitle(1033);
			return string.Format("{0} ({1})", title, this.FeatureID);
		}

		#endregion



	}
}
